<?php

namespace EthanZ\HyperfExt\Utils;

use Hyperf\DbConnection\Db;
use Hyperf\Di\Annotation\Inject;
use Hyperf\HttpServer\Contract\RequestInterface;
use Hyperf\Validation\ValidatorFactory;
use Hyperf\Validation\Validator;

/**
 * 自定义验证规则工具类
 */
class Rules extends ValidatorFactory
{


    #[Inject]
    protected RequestInterface   $request;


    /**
     * 电话验证
     *
     * @param string    $attribute  要被验证的属性名称.
     * @param mixed     $value      属性的值.
     * @param array     $parameters 传入验证规则的参数数组.
     * @param Validator $validator  Validator 实列.
     *
     * @return bool
     */
    public function phone(string $attribute, mixed $value, array $parameters, Validator $validator): bool
    {
        return !empty(preg_match('/^(1)\d{10}$/', $value));
    }


    /**
     * 密码
     *
     * @param string           $attribute  要被验证的属性名称.
     * @param mixed            $value      属性的值.
     * @param array            $parameters 传入验证规则的参数数组.
     * @param ValidatorFactory $validator  Validator 实列.
     *
     * @return bool
     */
    public function pwd(string $attribute, mixed $value, array $parameters, Validator $validator): bool
    {
        return !empty(preg_match('/(?=.*[a-z])(?=.*\d)(?=.*[#@!,~%^&*])[a-z\d#@!,~%^&*]{8,20}/', $value));
    }


    /**
     * 修改数据检查唯一性
     *
     * @param string    $attribute  要被验证的属性名称.
     * @param mixed     $value      属性的值.
     * @param array     $parameters 传入验证规则的参数数组.
     * @param Validator $validator  Validator 实列.
     *
     * @return mixed
     */
    public function isUnique(string $attribute, mixed $value, array $parameters, Validator $validator): bool
    {
        // 获取表名.
        $table = $parameters[0];
        // 获取排除字段名.
        $excludeFiled = $parameters[1];
        // 获取验重字段名.
        $field = $parameters[2] ?? $attribute;
        // 获取排除字段值.
        $excludeValue = $this->request->input($excludeFiled);

        $data = Db::table($table)
            ->select($field)
            ->where($field, $value)
            ->where($excludeFiled, '<>', $excludeValue)
            ->first();

        return empty($data);
    }
}
